// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

// ReSharper disable CheckNamespace
// ReSharper disable ClassNeverInstantiated.Global
// ReSharper disable CommentTypo
// ReSharper disable IdentifierTypo
// ReSharper disable InconsistentNaming
// ReSharper disable StringLiteralTypo
// ReSharper disable UnusedParameter.Local

/*
 * Ars Magna project, http://arsmagna.ru
 */

#region Using directives

using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Drawing;

using AM.Reporting.Utils;

#endregion

#nullable enable

namespace AM.Reporting
{
    /// <summary>
    /// Specifies a start and end line caps.
    /// </summary>
    [TypeConverter (typeof (TypeConverters.FRExpandableObjectConverter))]
    public class CapSettings
    {
        /// <summary>
        /// Gets or sets a width of the cap.
        /// </summary>
        [DefaultValue (8f)]
        public float Width { get; set; }

        /// <summary>
        /// Gets or sets a height of the cap.
        /// </summary>
        [DefaultValue (8f)]
        public float Height { get; set; }

        /// <summary>
        /// Gets or sets a cap style.
        /// </summary>
        [DefaultValue (CapStyle.None)]
        public CapStyle Style { get; set; }

        internal void GetCustomCapPath (out GraphicsPath path, out float inset)
        {
            path = new GraphicsPath();
            inset = 0;
            switch (Style)
            {
                case CapStyle.Arrow:
                    path.AddLine (new PointF (0, 0), new PointF (-Width, -Height));
                    path.AddLine (new PointF (0, 0), new PointF (Width, -Height));
                    break;

                case CapStyle.Circle:
                    path.AddEllipse (-Width / 2, -Height / 2, Width, Height);
                    inset = Height / 2;
                    break;

                case CapStyle.Square:
                    path.AddRectangle (new RectangleF (-Width / 2, -Height / 2, Width, Height));
                    inset = Height / 2;
                    break;

                case CapStyle.Diamond:
                    path.AddLine (new PointF (0, -Height / 1.4f), new PointF (-Width / 1.4f, 0));
                    path.AddLine (new PointF (-Width / 1.4f, 0), new PointF (0, Height / 1.4f));
                    path.AddLine (new PointF (0, Height / 1.4f), new PointF (Width / 1.4f, 0));
                    path.AddLine (new PointF (Width / 1.4f, 0), new PointF (0, -Height / 1.4f));
                    inset = Height / 1.4f;
                    break;
            }
        }

        /// <summary>
        /// Assigns values from another source.
        /// </summary>
        /// <param name="source">Source to assign from.</param>
        public void Assign (CapSettings source)
        {
            Width = source.Width;
            Height = source.Height;
            Style = source.Style;
        }

        /// <summary>
        /// Creates exact copy of this object.
        /// </summary>
        /// <returns>Copy of this object.</returns>
        public CapSettings Clone()
        {
            var result = new CapSettings();
            result.Assign (this);
            return result;
        }

        /// <inheritdoc/>
        public override bool Equals (object? obj)
        {
            var c = obj as CapSettings;
            return c != null && Width == c.Width && Height == c.Height && Style == c.Style;
        }

        /// <inheritdoc/>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        /// <summary>
        /// Serializes the cap settings.
        /// </summary>
        /// <param name="prefix">Name of the cap property.</param>
        /// <param name="writer">Writer object.</param>
        /// <param name="diff">Another cap to compare with.</param>
        /// <remarks>
        /// This method is for internal use only.
        /// </remarks>
        public void Serialize (string prefix, ReportWriter writer, CapSettings diff)
        {
            if (Width != diff.Width)
            {
                writer.WriteFloat (prefix + ".Width", Width);
            }

            if (Height != diff.Height)
            {
                writer.WriteFloat (prefix + ".Height", Height);
            }

            if (Style != diff.Style)
            {
                writer.WriteValue (prefix + ".Style", Style);
            }
        }

        /// <summary>
        /// Initializes a new instance of the <b>CapSettings</b> class with default settings.
        /// </summary>
        public CapSettings()
        {
            Width = 8;
            Height = 8;
        }
    }
}
